import { Component, OnInit, OnDestroy, EventEmitter } from '@angular/core';
import { Subscription } from "rxjs/Subscription";
import { SocketService } from "socket";
import { CmHttp } from "./../http-module/http.service";
import { SummaryAssistantService, STOCK_STATUS, SummaryWithTrading } from "summary-assistant";

@Component({
  // moduleId: module.id,
  selector: 'bidask',
  templateUrl: 'bidask.component.html',
  styleUrls: [
    "bidask.component.less"
  ],
  inputs: [
    "place",  // bidask 显示的位置，设定不同的样式, vtrade
    "quoteSource", // 包含quote信息的Observable
    "emptySource"  // 置空数据
  ],
  outputs: [
    "bidOrAskClick"
  ]
})
export class BidAskComponent implements OnInit, OnDestroy {
  stockInfo;
  bidOrAskClick = new EventEmitter();
  quoteSource;
  emptySource;
  detailSocketCb;
  entrustDiff;
  entrustRate;
  currentStock: SummaryWithTrading;
  stockStopt = false;
  quoteSubscription: Subscription;
  constructor(private http: CmHttp, private socket: SocketService) { }

  ngOnInit() {
    let { quoteSource, http, socket } = this;
    let that = this;
    this.quoteSubscription = quoteSource.
      subscribe((stockInfo: SummaryWithTrading) => {
        if (!stockInfo || stockInfo.isError)
            return;
            
        // console.debug("BIDASK: ", stockInfo);
        // 处理停盘数据
        if (stockInfo.stockStatus === STOCK_STATUS.STOP_AND_TRADING_DAY
          // || stockInfo.stockStatus === STOCK_STATUS.OCALL
          || (stockInfo.bid === "0,0,0,0,0,0,0,0,0,0" && stockInfo.ask === "0,0,0,0,0,0,0,0,0,0")
          || (stockInfo.bid === "" && stockInfo.ask === "")
        ) {
          this.stockStopt = true;
        } else {
          this.stockStopt = false;
        }
        this.currentStock = stockInfo;
        this.entrustRate = stockInfo.entrust_rate;
        this.entrustDiff = stockInfo.entrust_diff;
        this.stockInfo = getBidAsk(stockInfo);
        //socket.emit("sub", { channel: "detail", symbols: [stockInfo.symbol] });
      });
    this.detailSocketCb = detailSocketCb;
    socket.on("detail", this.detailSocketCb);
    function detailSocketCb(detail) {
      // console.debug("BidAsk Detail: ", detail, that);
      if (!that.currentStock) return;
      if (!detail) return;
      //增加防止错乱措施
      if (detail.symbol != that.currentStock.symbol) return;
      
      let d = detail; //adapt to v2 api
      //let d = detail[that.currentStock.symbol];
      that.currentStock = Object.assign({}, that.currentStock, d);
      that.stockStopt = false;
      if (d.ask) {
        that.stockInfo.ask = getBidOrAsk(d.ask);
      }
      if (d.bid) {
        that.stockInfo.bid = getBidOrAsk(d.bid);
      }
    }
    // 置空数据 for MRI and XBHS
    this.emptySource ? this.emptySource.subscribe((val: boolean) => {
      if (!val) return;
      this.socket.off("detail", this.detailSocketCb);
      this.stockStopt = true;
    }) : null;
  }

  ngOnDestroy() {
    this.quoteSubscription ? this.quoteSubscription.unsubscribe() : null;
    this.socket.off("detail", this.detailSocketCb);
  }

  // detail socket消息订阅回调
  // detailSocketCb(detail) {

  // }

  getPriceColor(amount) {
    let a = parseFloat(amount);
    if (isNaN(a)) return "";
    return a == this.currentStock.pre_close
      ? ""
      : a > this.currentStock.pre_close
        ? "text-color-red"
        : "text-color-green";
  }

  getLegendWidth(amount, totolMountArr) {
    // console.debug("%c Legend Width: ", "color: #f00", amount, totolMountArr)
    if (this.stockStopt) return "0";
    if (totolMountArr.every(bidAsk => +(bidAsk.amount) === 0)) {
      return "0";
    }
    return amount / totolMountArr.map(data => data ? parseFloat(data.amount) : 0).reduce((cur, next) => cur + next) * 100 + "%";
  }

  handleClick(entry, bidOrAsk) {
    console.debug("Bidask click: ", entry);
    this.bidOrAskClick.next(Object.assign({}, entry, { bidOrAsk }));
  }

}

const getValues = obj => Object.keys(obj).map(key => obj[key]);

const bidTransform = (bidObj, bidPriceOrAmount, index, bid) =>
  index % 2 !== 0 ?
    Object.assign({}, bidObj, { [Math.floor(index / 2)]: Object.assign({}, bidObj[Math.floor(index / 2)], { amount: bidPriceOrAmount }) }) :
    Object.assign({}, bidObj, { [Math.floor(index / 2)]: { price: bidPriceOrAmount } })

const getBidOrAsk = bidOrAsk =>
  !bidOrAsk || !bidOrAsk.length ? {} :
    getValues(
      bidOrAsk.
        split(",").
        reduce(bidTransform,
        {})
    );

const getBidAsk = stockInfo => {

  if (!stockInfo.bid) {
    return {
      bid: null,
      ask: null
    };
  }

  return {
    bid: getValues(
      stockInfo.bid.
        split(",").
        reduce(bidTransform,
        {})
    ),
    ask: getValues(
      stockInfo.ask.
        split(",").
        reduce(bidTransform,
        {})
    ),
  };
}